package org.example.domain.plugin.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 插件管理器
 */
@Slf4j
@Service
public class PluginManager {

    private final Map<String, AsyncSearchPlugin> pluginRegistry = new ConcurrentHashMap<>();
    private final List<AsyncSearchPlugin> plugins;

    public PluginManager(List<AsyncSearchPlugin> plugins) {
        this.plugins = plugins != null ? plugins : new ArrayList<>();
    }

    @PostConstruct
    public void init() {
        // 注册所有插件
        for (AsyncSearchPlugin plugin : plugins) {
            registerPlugin(plugin);
        }
        log.info("Initialized PluginManager with {} plugins: {}",
            pluginRegistry.size(),
            pluginRegistry.keySet());
    }

    /**
     * 注册插件
     */
    public void registerPlugin(AsyncSearchPlugin plugin) {
        if (plugin == null || plugin.getName() == null) {
            log.warn("Cannot register null plugin or plugin with null name");
            return;
        }

        pluginRegistry.put(plugin.getName().toLowerCase(), plugin);
        log.info("Registered plugin: {} (priority: {})", plugin.getName(), plugin.getPriority());
    }

    /**
     * 获取插件
     */
    public AsyncSearchPlugin getPlugin(String name) {
        if (name == null) {
            return null;
        }
        return pluginRegistry.get(name.toLowerCase());
    }

    /**
     * 获取所有插件
     */
    public List<AsyncSearchPlugin> getAllPlugins() {
        return new ArrayList<>(pluginRegistry.values());
    }

    /**
     * 获取启用的插件列表
     */
    public List<AsyncSearchPlugin> getEnabledPlugins(List<String> enabledPluginNames) {
        if (enabledPluginNames == null || enabledPluginNames.isEmpty()) {
            // 返回所有可用插件，按优先级排序
            return getAllPlugins().stream()
                    .filter(AsyncSearchPlugin::isAvailable)
                    .sorted(Comparator.comparingInt(AsyncSearchPlugin::getPriority))
                    .collect(Collectors.toList());
        }

        // 返回指定的插件，按优先级排序
        return enabledPluginNames.stream()
                .map(this::getPlugin)
                .filter(Objects::nonNull)
                .filter(AsyncSearchPlugin::isAvailable)
                .sorted(Comparator.comparingInt(AsyncSearchPlugin::getPriority))
                .collect(Collectors.toList());
    }

    /**
     * 根据优先级获取插件
     */
    public List<AsyncSearchPlugin> getPluginsByPriority(int maxPriority) {
        return getAllPlugins().stream()
                .filter(plugin -> plugin.getPriority() <= maxPriority)
                .filter(AsyncSearchPlugin::isAvailable)
                .sorted(Comparator.comparingInt(AsyncSearchPlugin::getPriority))
                .collect(Collectors.toList());
    }

    /**
     * 检查插件是否存在
     */
    public boolean hasPlugin(String name) {
        return name != null && pluginRegistry.containsKey(name.toLowerCase());
    }

    /**
     * 获取插件数量
     */
    public int getPluginCount() {
        return pluginRegistry.size();
    }

    /**
     * 获取可用插件数量
     */
    public int getAvailablePluginCount() {
        return (int) getAllPlugins().stream()
                .filter(AsyncSearchPlugin::isAvailable)
                .count();
    }

    /**
     * 获取插件状态信息
     */
    public Map<String, Object> getPluginStatus() {
        Map<String, Object> status = new HashMap<>();
        status.put("totalPlugins", getPluginCount());
        status.put("availablePlugins", getAvailablePluginCount());

        Map<String, Object> pluginDetails = new HashMap<>();
        for (AsyncSearchPlugin plugin : getAllPlugins()) {
            Map<String, Object> detail = new HashMap<>();
            detail.put("priority", plugin.getPriority());
            detail.put("available", plugin.isAvailable());
            detail.put("description", plugin.getDescription());
            pluginDetails.put(plugin.getName(), detail);
        }
        status.put("plugins", pluginDetails);

        return status;
    }
}